package com.huitong.common.mybatis.encrypt;

import cn.hutool.core.util.ReflectUtil;
import com.huitong.common.mybatis.annotation.EncryptField;
import com.huitong.common.mybatis.encrypt.encryptor.Encryptor;
import com.huitong.common.mybatis.enums.EncodeType;
import com.huitong.common.mybatis.properties.EncryptCustomProperties;

import java.lang.reflect.Field;

/**
 * 敏感字段加密算法管理器
 *
 * @author fromdrowning
 * @date 2024/4/11 22:21
 */
public class EncryptorManager {

    /**
     * 根据操作类型{@link HandleType}对敏感字段进行加密或解密
     *
     * @param object     待操作的敏感字段对象
     * @param handleType 操作类型
     * @throws IllegalAccessException 当敏感字段对象内的字段无法被访问时抛出此异常
     */
    public void handleFields(Object object, HandleType handleType) throws IllegalAccessException {
        Class<?> o = object.getClass();
        // 性能优化 方法上没有注解直接返回
        if (o.isAnnotationPresent(EncryptField.class)) {
            // 根据操作类型对敏感字段进行加密或解密
            for (Field field : o.getDeclaredFields()) {
                if (field.isAnnotationPresent(EncryptField.class) && field.getType() == STRING) {
                    field.setAccessible(true);
                    String value = String.valueOf(field.get(object));
                    field.set(object, handleType == HandleType.ENCRYPT ? encrypt(value) : decrypt(value));
                }
            }
        }
    }

    /**
     * {@link String}类对象
     */
    private static final Class<String> STRING = String.class;

    /**
     * 加密后的编码类型
     */
    private final EncodeType encodeType;

    /**
     * 加密算法
     */
    private final Encryptor encryptor;

    /**
     * 敏感字段加密算法管理器
     *
     * @param encryptCustomProperties 敏感字段加密自定义配置
     */
    public EncryptorManager(EncryptCustomProperties encryptCustomProperties) {
        this.encodeType = encryptCustomProperties.getEncodeType();
        this.encryptor = ReflectUtil.newInstance(encryptCustomProperties.getEncryptType().getClazz(), encryptCustomProperties);
        this.encryptor.verifyProperties();
    }

    /**
     * 操作类型
     *
     * @author fromdrowning
     * @date 2024/04/17 15:32
     */
    public enum HandleType {

        /**
         * 加密
         */
        ENCRYPT,

        /**
         * 解密
         */
        DECRYPT

    }

    /**
     * 加密
     *
     * @param value 需要加密的敏感字段值
     * @return 加密后的敏感字段值
     */
    private String encrypt(String value) {
        return encryptor.encrypt(value, encodeType);
    }

    /**
     * 解密
     *
     * @param value 需要解密的敏感字段值
     * @return 解密后的敏感字段值
     */
    private String decrypt(String value) {
        return encryptor.decrypt(value);
    }
}
